<template>
    <transition name="fade">
        <div ref="boxFrame" v-if="isShow" class="v-floater boxFrame" :style="style">
            <div class="box-tit" @mousedown="pointerDownListener" @touchstart="pointerDownListener">
                <div class="box-tit-lab">{{ label }}</div>

                <div
                    v-for="(obj, idx) in currentButtons"
                    :key="idx"
                    :class="['btn', 'box-tit-btn', obj.classes, obj.isIcon ? obj.label : '']"
                    @click="e => handleBtnClick(obj, e)"
                >
                    {{ obj.isIcon ? '' : obj.label }}
                </div>
            </div>
            <div class="box-con">
                <slot></slot>
            </div>
        </div>
    </transition>
</template>

<script>
import _ from 'lodash';
import Point from './Point.js';

export default {
    name: 'v-floater',
    props: {
        value: Boolean,
        id: String,
        label: String,
        width: Number,
        buttons: {
            type: Array,
            default: () => []
        },
        selectedIds: {
            type: Array,
            default: () => []
        },
        withGlass: Boolean,
        hasSelectAll: Boolean,
        hasLock: Boolean
        // isShow: Boolean
    },
    data() {
        return {
            currentValue: this.value,
            style: null,
            dragging: false,
            dragPos: {},
            currentButtons: this.buttons,
            currentIds: this.selectedIds
            // visibleTag: false
        };
    },
    computed: {
        isShow() {
            // let rtn = (this.$store && this.$store.state.status && this.$store.state.status.openedBoxes || []).indexOf(this.id) >= 0 || this.currentValue;
            // if (rtn && this.withGlass) this.openGlass();
            // return rtn;
            // if (rtn && this.withGlass) this.openGlass();
            return this.currentValue;
        },
        slotTable() {
            if (!this.$slots.default || !this.$slots.default[0] || !this.$slots.default[0].componentInstance) return;
            return this.$slots.default[0].componentInstance;
        },
        slotTableName() {
            return this.slotTable.trueName;
        }
    },
    watch: {
        value(val) {
            this.currentValue = val;
        },
        currentValue(val) {
            this.$emit('input', val);
            if (val) this.init();
            else this.hideGlass();
        },
        buttons() {
            this.initButtons();
        },
        selectedIds(val) {
            this.currentIds = val;
        },
        currentIds(val) {
            this.$emit('handleSelect', val);
        }
    },
    created() {
        // if (!this.id) console.error("v-floater's id is null...");
        // bus.on(this.id + '.init', this.init);
        // bus.on(this.id + '.show', this.show);
        // bus.on(this.id + '.hide', this.hide);
    },
    beforeDestroy: function () {
        // clear the listener
        // bus.off(this.id + '.init', this.init);
        // bus.off(this.id + '.show', this.show);
        // bus.off(this.id + '.hide', this.hide);
    },

    mounted() {
        this.init();
    },
    methods: {
        init() {
            if (!this.currentValue) return;
            // console.log(`v-floater.${this._uid}.init ... `);
            this.dialogGlass = null;
            if (this.withGlass) this.openGlass();

            // console.log(`v-floater.${this._uid}.init: `, this, this.$slots.default[0].componentInstance);
            this.initButtons();

            this.pushToFront();

            try {
                // try to run the subpage init func
                if (this.$slots.default[0] && this.$slots.default[0].context) {
                    let child = this.$slots.default[0].context,
                        childInitFunc = child.init;
                    // console.warn('v-floater.init: ', childInitFunc, typeof childInitFunc === 'function');
                    if (typeof childInitFunc === 'function') childInitFunc.bind(child)();
                }
            } catch (e) {
                console.warn('v-floater.init.error: ', e);
            }
        },
        initButtons() {
            let arr = [{ key: 'close', label: 'icon icon-close', isIcon: true }];
            if (this.hasLock) arr.unshift({ key: 'lock', label: 'icon icon-lock', isIcon: true });
            if (this.hasSelectAll) arr.unshift({ key: 'checkbox', label: 'icon icon-checkbox-o', isIcon: true });

            this.currentButtons = this.buttons.concat(arr);
        },
        update() {},
        pointerDownListener(e) {
            if (e.target.className.indexOf('Button') > -1) return;
            // console.log('v-floater.pointerDownListener: ', e.target, this.$refs.boxFrame);
            // console.log('v-floater.pointerDownListener: ', this.$refs.boxFrame.parentNode);

            this.dragging = true;

            this.dragPos = Point.getInstanceByMouseOffset(e, this.$refs.boxFrame);
            this.pushToFront();

            window.document.addEventListener('mousemove', this.pointerMoveListener);
            window.document.addEventListener('touchmove', this.pointerMoveListener);
            window.document.addEventListener('mouseup', this.pointerUpListener);
            window.document.addEventListener('touchend', this.pointerUpListener);
        },
        pointerMoveListener: _.throttle(function (e) {
            e.preventDefault();
            if (!this.dragging) return;

            let pagePos = Point.getInstanceByMouseOffset(e, this.$refs.boxFrame.parentNode);
            // console.log('---> ', this.dragPos.x, this.dragPos.y, pagePos.x, pagePos.y);
            this.style = {
                width: this.width + 'px' || 'auto',
                top: Math.max(0, pagePos.y - this.dragPos.y) + 'px',
                left: pagePos.x - this.dragPos.x + 'px'
            };
        }, 24),
        pointerUpListener() {
            this.dragging = false;
            window.document.removeEventListener('mousemove', _.throttle(this.pointerMoveListener, 50));
            window.document.removeEventListener('touchmove', _.throttle(this.pointerMoveListener, 50));
            window.document.removeEventListener('mouseup', this.pointerUpListener);
            window.document.removeEventListener('touchend', this.pointerUpListener);
        },
        pushToFront() {
            if (!this.currentValue) return;

            if (!this.ptfMaxTry) this.ptfMaxTry = 1;
            if (!this.$refs.boxFrame && this.ptfMaxTry < 20) {
                // console.log(`v-floater.${this.id}.pushToFront: ->`, this.currentValue, this.ptfMaxTry);
                this.ptfMaxTry++;
                return setTimeout(() => {
                    this.pushToFront();
                }, 50);
            } else {
                this.ptfMaxTry = 1;

                // console.log(`v-floater.${this.id}.pushToFront: ------> `, this.$refs.boxFrame);
                let centerX = window.innerWidth / 2,
                    centerY = window.innerHeight / 2;
                this.style = {
                    width: this.width + 'px' || 'auto',
                    top: centerY - this.$refs.boxFrame.scrollHeight / 2 + 'px',
                    left: centerX - this.$refs.boxFrame.scrollWidth / 2 + 'px'
                };

                let boxes = document.getElementsByClassName('boxFrame');
                let i,
                    b,
                    currentIndex,
                    maxIndex = 0,
                    indices = [],
                    gapIndex;
                for (i = 0; i < boxes.length; i++) {
                    b = boxes[i];
                    currentIndex = Number(b.style.zIndex);
                    if (currentIndex > maxIndex) maxIndex = currentIndex;
                }
                this.$refs.boxFrame.style.zIndex = String(++maxIndex);
                for (i = 0; i < boxes.length; i++) indices.push(Number(boxes[i].style.zIndex));
                for (i = 1; i < maxIndex; i++)
                    if (indices.indexOf(i) < 0) {
                        gapIndex = i;
                        break;
                    }
                for (i = 0; i < boxes.length; i++) {
                    b = boxes[i];
                    currentIndex = Number(b.style.zIndex);
                    if (currentIndex > gapIndex) b.style.zIndex = String(--currentIndex);
                }
                // console.warn(`v-floater.${this.id}.pushToFront: `, this.$refs.boxFrame.style.zIndex);
            }
        },

        handleBtnClick(obj, e) {
            // console.log('v-floater.handleBtnClick: ', obj);
            if (obj && obj.key === 'checkbox' && this.slotTableName) {
                // bus.emit(this.slotTableName + '.toggleSelectAll');
                if (this.slotTable && typeof this.slotTable.toggleSelectAll === 'function')
                    this.slotTable.toggleSelectAll();
            } else if (obj && obj.key === 'lock') this.$emit('handleLock', this.selectedIds, e);
            else if (obj && obj.key === 'close') this.hide();
            else if (typeof obj.func === 'function') obj.func(e);
        },

        openGlass() {
            if (this.dialogGlass || document.getElementsByClassName('dialogGlass').length) return;
            if (!this.maxTry) this.maxTry = 1;
            if ((!this.$refs.boxFrame || !this.$refs.boxFrame.style.zIndex) && this.maxTry < 20) {
                // console.log(`v-floater.${this.id}.openGlass: maxTry: `, this.maxTry);
                this.maxTry++;
                return setTimeout(() => {
                    this.openGlass();
                }, 50);
            } else if (!this.dialogGlass) {
                this.maxTry = 1;
                this.dialogGlass = document.createElement('div');
                this.dialogGlass.className = 'dialogGlass';
                // console.log(`v-floater.${this.id}.openGlass: `, this.style, ', ', this.$refs.boxFrame.style.zIndex);
                this.dialogGlass.style.zIndex = String(Number(this.$refs.boxFrame.style.zIndex || 1) - 1);
                document.body.appendChild(this.dialogGlass);
                // dom.showElement(this.dialogGlass);
            }
        },
        hideGlass() {
            if (this.dialogGlass) {
                // dom.hideAndRemoveElement(this.dialogGlass);
            } else {
                let arr = document.getElementsByClassName('dialogGlass') || [];
                // console.log(`v-floater.${this.id}.hideGlass: `, arr);
                // for (let i = 0; i < arr.length; i++) dom.hideAndRemoveElement(arr[i]);
            }
        },
        show(withGlass) {
            console.log(`v-floater.${this.id}.${this._uid}.show: `, withGlass);
            if (!this.currentValue) this.currentValue = true;
            if (withGlass) this.openGlass();

            // this.$store && this.$store.commit(OPEN_BOX, this.id);
            // bus.emit('index.handleOpened', this.id);
            // // this.init();
            // this.$nextTick(() => this.init());
        },
        hide() {
            // console.log('v-floater.hide: ', ...arguments);
            console.log(`v-floater.${this.id}.${this._uid}.hide: `);
            // if (this.dialogGlass) dom.hideAndRemoveElement(this.dialogGlass);
            this.hideGlass();

            if (this.currentValue) this.currentValue = false;
            // this.$store && this.$store.commit(CLOSE_BOX, this.id);
            // bus.emit('index.handleClosed', this.id);
            // // bus.emit('p-sitemap.updateContourProperty', );
        }
    }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<!-- <style scoped lang="scss"> -->
<style lang="scss">
.v-floater {
    cursor: pointer;
    position: absolute;
    background: whiteSmoke;
    box-shadow: 0 0 8px gray;
    border: 1px solid rgba(0, 0, 0, 0.3);
    z-index: 0;

    .box-tit {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        background-color: #eaeaea;
    }

    .box-tit-lab {
        // float: left;
        flex: 1 1 auto;
        text-align: left;
        font-weight: 700;
        // line-height: 22px;
    }

    .box-tit-btn {
        // float: right;
        line-height: 22px;
        padding: 0 7px;
        text-align: center; /* only for fixed width buttons */
        border-left: 1px solid silver;
        border-bottom: 1px solid silver;
        transition: color 500ms, border 500ms, background-color 500ms;

        &.box-tit-btn:hover {
            background-color: silver;
            transition: color 100ms, border 100ms, background-color 100ms;
        }

        &.checked {
            color: white;
            border-color: dimgray;
            background-color: dimgray;
        }
    }

    .boxIconButton {
        width: 22px;
        padding: 0;
        background-repeat: no-repeat;
        background-origin: content-box;
        background-size: 14px;
        background-position: center;
    }

    .boxCloseButton {
        width: 22px;
        font-size: 28px;
        padding: 0;
        border-right: 1px solid silver;
        overflow: hidden;
    }

    .boxCloseButton:hover {
        color: white;
        border-color: red;
        background-color: red;
    }

    .boxSubmitButton:hover {
        color: white;
        border-color: green;
        background-color: green;
    }

    .boxOptionButton {
        color: white;
        border-color: dimgray;
        background-color: dimgray;
    }

    .boxOptionButton:hover {
        background-color: dimgray;
    }
}
</style>
